package org.springframework.web.servlet.ajax.json;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONString;

/**For some reason the subclass didn't respect the ordering of a LinkedHashMap.
 * 
 * @author Charles Tassoni
 */
public class RespectsOrderJSONObject extends JSONObject {

	public RespectsOrderJSONObject() {
	}

	/**
	 * Taken from JSONObject, but the map is passed in. Can't figure out why the
	 * original didn't respect LinkedHashMap keyset ordering, but indeed it did
	 * not.
	 */
	public String toString(Map map) {
	        try {
	            Iterator     keys = map.keySet().iterator();
	            StringBuffer sb = new StringBuffer("{");

	            while (keys.hasNext()) {
	                if (sb.length() > 1) {
	                    sb.append(',');
	                }
	                Object o = keys.next();
	                sb.append(quote(o.toString()));
	                sb.append(':');
	                sb.append(valueToString(map.get(o)));
	            }
	            sb.append('}');
	            return sb.toString();
	        } catch (Exception e) {
	            return null;
	        }
	    }

	 //Taken directly from JSONObject
	  static String valueToString(Object value) throws JSONException {
	        if (value == null || value.equals(null)) {
	            return "null";
	        }
	        if (value instanceof JSONString) {
	            Object o;
	            try {
	                o = ((JSONString)value).toJSONString();
	            } catch (Exception e) {
	                throw new JSONException(e);
	            }
	            if (o instanceof String) {
	                return (String)o;
	            }
	            throw new JSONException("Bad value from toJSONString: " + o);
	        }
	        if (value instanceof Number) {
	            return numberToString((Number) value);
	        }
	        if (value instanceof Boolean || value instanceof JSONObject ||
	                value instanceof JSONArray) {
	            return value.toString();
	        }
	        if (value instanceof Map) {
	            return new JSONObject((Map)value).toString();
	        }
	        if (value instanceof Collection) {
	            return new JSONArray((Collection)value).toString();
	        }
	        if (value.getClass().isArray()) {
	            return new JSONArray(value).toString();
	        }
	        return quote(value.toString());
	    }

}
